package org.xjtu.weteam.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletRequest;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
public class FileUtils {

    private static final Set<String> ALLOWED_EXTENSIONS = new HashSet<>(Arrays.asList(
            "jpg", "jpeg", "png", "gif", "pdf", "doc", "docx",
            "xls", "xlsx", "ppt", "pptx", "txt", "zip", "rar"
    ));

    private static final long MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1GB

    /**
     * 保存上传的文件
     * @param file 上传的文件
     * @param baseUploadPath 基础上传路径
     * @return 保存后的文件相对路径
     */
    public static String saveUploadedFile(MultipartFile file, String baseUploadPath) throws IOException {
        // 文件校验
        validateFile(file);

        // 生成文件存储路径
        Path uploadPath = Paths.get(baseUploadPath);
        String datePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
        Path finalPath = uploadPath.resolve(datePath);
        Files.createDirectories(finalPath);

        // 生成唯一文件名
        String extension = getFileExtension(file.getOriginalFilename());
        String newFileName = UUID.randomUUID().toString() + "." + extension;

        // 保存文件
        Path targetPath = finalPath.resolve(newFileName);
        Files.copy(file.getInputStream(), targetPath);

        return baseUploadPath + "/" + datePath + "/" + newFileName;
    }

    /**
     * 生成文件下载响应
     */
    public static ResponseEntity<Resource> generateDownloadResponse(String filePath, String fileName,
                                                                    HttpServletRequest request) throws IOException {
        Path path = Paths.get(filePath);
        Resource resource = new FileSystemResource(path.toFile());

        if (!resource.exists()) {
            return ResponseEntity.notFound().build();
        }

        // 处理文件名编码
        String encodedFileName = encodeFileName(fileName, request.getHeader("User-Agent"));

        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"")
                .body(resource);
    }

    /**
     * 生成文件预览信息
     */
    public static Map<String, Object> generatePreviewInfo(String fileName, String filePath, Integer fileId, String baseUrl) {
        Map<String, Object> previewInfo = new HashMap<>();
        previewInfo.put("fileName", fileName);
        previewInfo.put("fileId", fileId);  // 添加fileId

        String fileType = getFileExtension(fileName);
        previewInfo.put("fileType", fileType);

        // 构建下载URL
        String downloadUrl = baseUrl + "/api/file/download/" + fileId;

        // 根据文件类型设置预览类型
        switch (fileType.toLowerCase()) {
            case "jpg":
            case "jpeg":
            case "png":
            case "gif":
                previewInfo.put("previewType", "image");
                break;
            case "pdf":
                previewInfo.put("previewType", "pdf");
                break;
            case "doc":
            case "docx":
                previewInfo.put("previewType", "doc");
                break;
            case "xls":
            case "xlsx":
                previewInfo.put("previewType", "xls");
                break;
            case "ppt":
            case "pptx":
                previewInfo.put("previewType", "ppt");
                break;
            default:
                previewInfo.put("previewType", "unsupported");
        }

        // 统一使用下载URL
        previewInfo.put("downloadUrl", downloadUrl);

        // 记录原始路径（如果需要）
        previewInfo.put("filePath", filePath);

        log.debug("生成预览信息: fileName={}, fileType={}, downloadUrl={}", fileName, fileType, downloadUrl);
        return previewInfo;
    }

    /**
     * 删除文件
     */
    public static boolean deleteFile(String filePath) {
        try {
            Path path = Paths.get(filePath);
            return Files.deleteIfExists(path);
        } catch (IOException e) {
            log.error("删除文件失败: {}", filePath, e);
            return false;
        }
    }

    // 私有辅助方法
    private static void validateFile(MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            throw new IOException("文件为空");
        }
        if (file.getSize() > MAX_FILE_SIZE) {
            throw new IOException("文件大小超过限制(1GB)");
        }
        String extension = getFileExtension(file.getOriginalFilename());
        if (!ALLOWED_EXTENSIONS.contains(extension.toLowerCase())) {
            throw new IOException("不支持的文件类型");
        }
    }

    public static String getFileExtension(String filename) {
        if (filename == null) return "";
        int dotIndex = filename.lastIndexOf('.');
        return (dotIndex == -1) ? "" : filename.substring(dotIndex + 1).toLowerCase();
    }

    private static String encodeFileName(String fileName, String userAgent) throws IOException {
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            return java.net.URLEncoder.encode(fileName, "UTF-8");
        }
        return new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
    }
}
